package service

import (
	"context"
	_ "go-im/docs" // 千万不要忘了导入把你自己项目上一步生成的docs
	"go-im/src/helper"
	"go-im/src/model"
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	_ "github.com/swaggo/gin-swagger"
)

// GetPostListHandler2 升级版帖子列表接口
//
//	@Summary		升级版帖子列表接口
//	@Description	可按社区按时间或分数排序查询帖子列表接口
//	@Tags			帖子相关接口
//	@Accept			application/json
//	@Produce		application/json
//	@Param			Authorization	header	string	false	"Bearer 用户令牌"
//	@Security		ApiKeyAuth
//	@Router			/posts2 [get]
func Login(ctx *gin.Context) {
	account := ctx.PostForm("account")
	password := ctx.PostForm("password")
	if account == "" || password == "" {
		ctx.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "account or password is empty",
		})
		return
	}
	ub, err := model.GetUserBasicByAccountPassword(account, password)

	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "username or password error: " + err.Error(),
		})
		return
	}

	token, err := helper.GenToken(ub.Identity, ub.Email)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "server internal error: " + err.Error(),
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "ok",
		"data": gin.H{
			"token": token,
		},
	})
}

func UserDetail(c *gin.Context) {
	// check auth
	u, _ := c.Get("user_claims")
	uc := u.(*helper.UserClaim)
	log.Printf("Identity from token: %s", uc.Identity) // 打印 Identity 值

	ub, err := model.GetUserBasicByIdentity(uc.Identity)
	if err != nil {
		log.Printf("failed to get user: %v\n", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "failed to get user: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "ok",
		"data": ub,
	})
}

func UserQuery(c *gin.Context) {
	// param
	account := c.Query("account")
	if account == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "param account error",
		})
		return
	}

	ub, err := model.GetUserBasicByAccount(account)
	if err != nil {
		log.Panicln("failed to get user: ", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "failed to get user",
		})
		return
	}

	uc := c.MustGet("user_claims").(*helper.UserClaim)
	data := model.UserQueryResponse{
		NickName: ub.NickName,
		Sex:      ub.Sex,
		Email:    ub.Email,
		Avatar:   ub.Avatar,
		IsFriend: false,
	}

	if model.JudgeUserIsFriend(ub.Identity, uc.Identity) {
		data.IsFriend = true
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "query user ok",
		"data": data,
	})
}

func SendCode(c *gin.Context) {
	email := c.PostForm("email")
	if email == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "email can not be empty",
		})
		return
	}
	cnt, err := model.GetUserBasicCountByEmail(email)
	if err != nil {
		log.Println("failed to get user basic: ", err)
		return
	}

	if cnt > 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "already exisits email, use new one",
		})
		return
	}

	code := helper.GenCode()
	err = helper.SendCode(email, code)
	if err != nil {
		log.Println("failed to send code: ", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "failed to send code: " + err.Error(),
		})
		return
	}

	if err = model.RDB.Set(context.Background(),
		helper.RegisterPrefix+email,
		code,
		time.Second*time.Duration(helper.ExpireTime),
	).Err(); err != nil {
		log.Println("failed to redis set: ", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "server internal error: " + err.Error(),
		})
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "send email validate code ok",
	})
}

func Register(c *gin.Context) {
	// require email validate code
	code := c.PostForm("code")
	email := c.PostForm("email")
	account := c.PostForm("account")
	password := c.PostForm("password")
	if code == "" || email == "" || account == "" || password == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "params code, email, account, password error",
		})
		return
	}

	// check if account is unique
	cnt, err := model.GetUserBasicCountByAccount(account)
	if err != nil {
		log.Panicln("user is not unique: ", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "server internal error: " + err.Error(),
		})
		return
	}

	if cnt > 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "account is already in used",
		})
		return
	}
	// check redis email validate code
	r, err := model.RDB.Get(context.Background(), helper.RegisterPrefix+email).Result()
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "email validate code error",
		})
		return
	}

	if r != code {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "email validate code not ok",
		})
		return
	}

	ub := &model.UserBasic{
		Identity:  helper.UUID(),
		Account:   account,
		Password:  helper.GetMd5(password),
		Email:     email,
		CreatedAt: time.Now().Unix(),
		UpdatedAt: time.Now().Unix(),
	}

	err = model.InsertOneUserBasic(ub)
	if err != nil {
		log.Println("failed to insert one user: ", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "server internal error: " + err.Error(),
		})
		return
	}
	token, err := helper.GenToken(ub.Identity, ub.Email)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "server internal error: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "ok",
		"data": gin.H{
			"token": token,
		},
	})
}

func FriendAdd(c *gin.Context) {
	account := c.PostForm("account")
	if account == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "params account is error",
		})
		return
	}

	ub, err := model.GetUserBasicByAccount(account)
	if err != nil {
		log.Println("failed to get user: ", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "failed to get user: " + err.Error(),
		})
		return
	}

	uc := c.MustGet("user_claims").(*helper.UserClaim)

	if model.JudgeUserIsFriend(ub.Identity, uc.Identity) {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "already friends, not allow to repeat add",
		})
		return
	}
	// keep room
	rb := &model.RoomBasic{
		Identity:     helper.UUID(),
		UserIdentity: uc.Identity,
		CreatedAt:    time.Now().Unix(),
		UpdatedAt:    time.Now().Unix(),
	}

	if err = model.InsertOneRoomBasic(rb); err != nil {
		log.Println("failed to insert room basic: ", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "failed to insert room basic",
		})
		return
	}

	// save user and room
	ur := &model.UserRoom{
		UserIdentity: uc.Identity,
		RoomIdentity: rb.Identity,
		RoomType:     1,
		CreatedAt:    time.Now().Unix(),
		UpdatedAt:    time.Now().Unix(),
	}
	if err = model.InsertOneUserRoom(ur); err != nil {
		log.Println("failed to insert user room: ", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "failed to insert user room",
		})
		return
	}

	ur = &model.UserRoom{
		UserIdentity: ub.Identity,
		RoomIdentity: rb.Identity,
		RoomType:     1,
		CreatedAt:    time.Now().Unix(),
		UpdatedAt:    time.Now().Unix(),
	}

	if err = model.InsertOneUserRoom(ur); err != nil {
		log.Println("failed to insert user room: ", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "failed to insert user room",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "friend add ok",
	})
}

// @Summary	删除friend
func FriendDelete(c *gin.Context) {
	identity := c.Query("identity")
	if identity == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "params identity is error",
		})
		return
	}

	uc := c.MustGet("user_claims").(*helper.UserClaim)

	roomIdentity := model.GetUserRoomIdentity(identity, uc.Identity)
	if roomIdentity == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "not friends, no need to delete",
		})
		return
	}

	if err := model.DeleteUserRoom(roomIdentity); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "failed to delete user room",
		})
		return
	}

	if err := model.DeleteRoomBasic(roomIdentity); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "failed to delete room basic",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "delete friend ok",
	})
}

func UserComplete(c *gin.Context) {
	// 从 user_claims 获取当前用户信息
	uc := c.MustGet("user_claims").(*helper.UserClaim)

	// 绑定请求数据到结构体
	var req struct {
		Nickname string `json:"nickname" binding:"omitempty"`
		Sex      int    `json:"sex" binding:"omitempty"`
		Avatar   string `json:"avatar" binding:"omitempty"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code": -1,
			"msg":  "invalid request data: " + err.Error(),
		})
		return
	}

	// 更新用户信息
	err := model.UpdateUserProfile(uc.Identity, req.Nickname, req.Sex, req.Avatar)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code": -1,
			"msg":  "failed to update user profile: " + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "user profile updated successfully",
	})
}
